package Controller;
import gui.Form;
import connection.SensorMessage;
import connection.SensorTypes;
import javax.swing.text.BadLocationException;



/**
 * An object (car, bus, pedestrian or cyclist) to be rendered
 * @author imahilus
 */
public class SimulatorObject
{
    private int                 xPosition    = -1;
    private int                 yPosition    = -1;
    private boolean             vertical     = false;
    private int                 length       = 1;
    private char                graphic      = '?';
    public  int                 lane         = -1;
    private int                 nextWaypoint = 1;
    private SimulatorObjectType type         = SimulatorObjectType.pedestrian;



    public enum SimulatorObjectType
    {
        car, bus, pedestrian, cyclist,
        motorised; //motorised is either car or bus
    }



    public SimulatorObject(int objectLane, SimulatorObjectType objectType)
    {
        lane = objectLane;
        if((lane >= 0)&&(lane <= 27))
        {
            xPosition = SimulatorWaypoints.lanes[lane].spawnPoint[0];
            yPosition = SimulatorWaypoints.lanes[lane].spawnPoint[1];
            if( (lane <= 7)||
                ((lane >= 14)&&(lane <= 20)) )
            {
                vertical = true;
            }
            /* //its an abstract representation, making the bus double as long as a car won't serve any real purpose
            if(type == SimulatorObjectType.bus)
            {
                length = 2;
            }
            */
            if(objectType == SimulatorObjectType.motorised)
            {
                objectType = Math.random() > 0.8 ? SimulatorObjectType.bus : SimulatorObjectType.car;
            }
            switch(objectType)
            {
                case bus:          //dutch name ; english name ; (using the dutch name to avoid duplicate letters)
                    graphic = 'B'; //bus        ; bus
                    break;         //
                case car:          //
                    graphic = 'A'; //auto       ; car
                    break;         //
                case cyclist:      //
                    graphic = 'f'; //fietser    ; cyclist
                    break;         //
                case pedestrian:   //
                    graphic = 'v'; //voetganger ; pedestrian
                    break;
                default:
                    break;
            }
            type = objectType;
        }
    }



    /**
     * Move the object, if possible. It will determine its own route as set by the waypoints of the lane it was assigned to.
     */
    public void Move()
    {
        int[] pointToMoveTo = getNextWaypoint();

        //check in which direction to move and determine the new coordinates
        int xDirection = pointToMoveTo[0]-xPosition;
        int yDirection = pointToMoveTo[1]-yPosition;
        int[] newPos   = {0, 0}; //x1, x2 and y
        if(xDirection > 0) //move right
        {
            newPos[0] = xPosition+2;
            newPos[1] = yPosition;
        }
        else
        if(xDirection < 0) //move left
        {
            newPos[0] = xPosition-2;
            newPos[1] = yPosition;
        }
        else
        if(yDirection > 0) //move down
        {
            newPos[0] = xPosition;
            newPos[1] = yPosition+1;
        }
        else
        if(yDirection < 0) //move up
        {
            newPos[0] = xPosition;
            newPos[1] = yPosition-1;
        }

        System.out.println(xPosition+","+yPosition+" - "+newPos[0]+","+newPos[1]);

        //see if the new coordinates are empty, can't move if it isn't (green traffic lights aren't drawn,
        String position = "??";
        try { position = Form.Crossing.getText((newPos[1]*SimulatorWaypoints.lineWidth)+newPos[0], 2); } catch(BadLocationException e) { }
        System.out.println(position);
        if(position.equalsIgnoreCase("  "))
        {
            //empty spot, move the object
            char[] crossing = Form.Crossing.getText().toCharArray();
            crossing = drawObject(crossing, xPosition, yPosition, ' ');
            xPosition = newPos[0];
            yPosition = newPos[1];
            if((newPos[0] == pointToMoveTo[0])&&(newPos[1] == pointToMoveTo[1]))
            {
                nextWaypoint += 1;
                if((nextWaypoint == 2)&&((this.type == SimulatorObjectType.car)||(type == SimulatorObjectType.bus)))
                {
                    triggerOneMeterLoop();
                }
                pointToMoveTo = getNextWaypoint();
                xDirection    = pointToMoveTo[0]-xPosition;
                yDirection    = pointToMoveTo[1]-yPosition;
            }
            crossing = drawObject(crossing, newPos[0], newPos[1], graphic);
            Form.Crossing.setText(new String(crossing));
        }
    }
    
    
    
    public char[] drawObject(char[] crossing, int xPos, int yPos, char charGraphic)
    {
        if(nextWaypoint < 4) //don't draw the object if it is on the despawn waypoint
        {
            int x = (yPos*SimulatorWaypoints.lineWidth)+xPos;
            crossing[x]   = charGraphic;
            crossing[x+1] = charGraphic;
            /*
            if(xDirection != 0) //move horizontal
            {
                for(int x = xPos+1; x >= xPos-((length-1)*2); x -= 1)
                {
                    crossing[(yPos*SimulatorWaypoints.lineWidth)+x] = charGraphic;
                }
            }
            else
            if(yDirection != 0) //move vertical
            {
                for(int x = xPos+((length-1)*SimulatorWaypoints.lineWidth); x >= xPos; x -= SimulatorWaypoints.lineWidth)
                {
                    crossing[x]   = charGraphic;
                    crossing[x+1] = charGraphic;
                }
            }
            */
        }
        return crossing;
    }
    
    
    
    public int[] getNextWaypoint()
    {
        int[] pointToMoveTo;
        switch(nextWaypoint)
        {
            case 1: //move to gatepoint
                pointToMoveTo = SimulatorWaypoints.lanes[lane].gatePoint;
                break;
            case 2: //move to turnpoint
                pointToMoveTo = SimulatorWaypoints.lanes[lane].turnPoint;
                break;
            case 3: //move to despawnpoint
                pointToMoveTo = SimulatorWaypoints.lanes[lane].despawnPoint;
                break;
            default: //remove
                pointToMoveTo = new int[]{-1, -1};
                break;
        }
        return pointToMoveTo;
    }



    public boolean mayDelete()
    {
        if(nextWaypoint == 4) { return true; }
        return false;
    }



    public void triggerOneMeterLoop()
    {
        //the property 'lane' can be used to send the signal, this is the index number of the lane this object is on
        //the property 'type' can be used to determine whether this is a bus or a car, in case it matters
        SensorMessage msg = new SensorMessage();
        msg.setLane(this.lane);
        msg.setSensor(SensorTypes.M1);
        SimulatorController.relay.addSensorMessage(msg);
    }
}
